package com.social.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.social.constant.MessageConstant;
import com.social.dao.PersonnelDao;
import com.social.pojo.Personnel;
import com.social.pojo.Result;
import com.social.pojo.SysUser;
import com.social.pojo.dto.UserDTO;
import com.social.pojo.vto.PersonnelVTO;
import com.social.service.PersonnelService;
import com.social.service.SysUserService;
import com.social.utils.UserHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.social.constant.RedisConstants.*;

/**
 * @BelongsProject: social
 * @BelongsPackage: com.social.service.impl
 * @Author: zhm
 * @CreateTime: 2022-10-06  17:34
 * @Description: TODO
 * @Version: 1.0
 */
@Service
public class PersonnelServiceImpl extends ServiceImpl<PersonnelDao, Personnel> implements PersonnelService {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private PersonnelDao personnelDao;

    @Autowired
    private SysUserService sysUserService;

    @Override
    public Result insert(Personnel personnel) {
        /**
         * 新增居民信息
         */
        Long edit_id = UserHolder.getUser().getId();
        personnel.setEditor_id(edit_id);
        SysUser sysUser = sysUserService.findByPhone(personnel.getPhone());
        if (sysUser != null) {
            personnel.setUsername(sysUser.getUsername());
        }else {
            personnel.setUsername("");
        }

        boolean isSave = save(personnel);
        if (!isSave) {
            return Result.fail(201, MessageConstant.ADD_PERSON_FAIL);
        }
        return Result.ok(200);
    }

    @Override
    public Result deleteById(Integer id) {
        /**
         * 根据id删除居民信息
         */
        boolean isDelete = removeById(id);
        if (!isDelete){
            return Result.fail(201, MessageConstant.PERSON_DELETE_FAIL);
        }

        String key = PERSON_ID_KEY + id;
        stringRedisTemplate.delete(key);
        return Result.ok(200);
    }

    @Override
    public Result update(Personnel personnel) {
        /**
         * 修改用户信息
         */
        boolean isUpdate = updateById(personnel);
        if (!isUpdate) {
            return Result.fail(201, MessageConstant.PERSON_UPDATE_FAIL);
        }

        String key = PERSON_ID_KEY + personnel.getId();
        stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(personnel), PERSON_ID_TTL, TimeUnit.MINUTES);
        return Result.ok(200);
    }

    @Override
    public Result findAll(Integer size, Integer index) {

        UserDTO user = UserHolder.getUser();
        System.out.println("UserHolder在controller中的测试：" + user);
        IPage<Personnel> page = personnelDao
                .selectPage(new Page<>(index, size), null);
        List<Personnel> records = page.getRecords();

        if (records == null) {
            return Result.fail(201, "未录入居民信息");
        }
        return Result.ok(200, records);
    }

    @Override
    public Result findByTelephone(String phone) {

        String key = PERSON_PHONE_KEY + phone;

        String Json = stringRedisTemplate.opsForValue().get(key);

        if (StrUtil.isNotBlank(Json)) {
            return Result.ok(200, JSONUtil.toBean(Json, Personnel.class));
        }

        QueryWrapper<Personnel> wrapper = Wrappers.query();
        wrapper.eq("phone", phone);
        Personnel personnel = getOne(wrapper);

        if (personnel == null) {
            return Result.fail(201, "未查询到对应居民信息");
        }

        stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(personnel), PERSON_PHONE_TTL, TimeUnit.MINUTES);

        return Result.ok(200, personnel);
    }

    @Override
    public Result findById(Integer id) {
        String key = PERSON_ID_KEY + id;

        String Json = stringRedisTemplate.opsForValue().get(key);

        if (Json != null) {
            return Result.ok(200, JSONUtil.toBean(Json, Personnel.class));
        }

        Personnel personnel = getById(id);

        if (personnel == null) {
            return Result.fail(201, "未查询到居民信息");
        }

        stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(personnel), PERSON_ID_TTL, TimeUnit.MINUTES);

        return Result.ok(200, personnel);
    }

    @Override
    public Result findByUsername(String username) {
        String key = PERSON_USERNAME_KEY + username;

        String Json = stringRedisTemplate.opsForValue().get(key);

        if (Json != null) {
            return Result.ok(200, JSONUtil.toBean(Json, Personnel.class));
        }

        QueryWrapper<Personnel> wrapper = Wrappers.query();
        wrapper.eq("username", username);

        Personnel personnel = getOne(wrapper);

        if (personnel == null) {
            return Result.fail(201, "未查询到居民信息");
        }

        stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(personnel), PERSON_USERNAME_TTL, TimeUnit.MINUTES);

        return Result.ok(200, personnel);
    }

    @Override
    public Result findByEditId(PersonnelVTO personnelVTO) {
        QueryWrapper<Personnel> wrapper = Wrappers.query();
        wrapper.eq("edit_id", personnelVTO.getEdit_id());

        IPage<Personnel> page = personnelDao.selectPage(new Page<>(personnelVTO.getSize(), personnelVTO.getIndex()), wrapper);
        List<Personnel> list = page.getRecords();

        if (list == null) {
            return Result.fail(201, "改用户未进行编辑");
        }

        return Result.ok(200, list);
    }

    @Override
    public Result findByCity(String city, String street) {
        if (street == null) {
            String key = PERSON_CITY_KEY + city;
            String Json = stringRedisTemplate.opsForValue().get(key);
            if (Json != null) {
                return Result.ok(200, JSONUtil.toList(Json, Map.class));
            }
            QueryWrapper<Personnel> queryWrapper = new QueryWrapper<>();
            queryWrapper
                    .eq("city", city)
                    .select("street", "count(*) as num")
                    .groupBy("street");
            List<Map<String, Object>> maps = personnelDao.selectMaps(queryWrapper);
            System.out.println(maps);
            stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(maps), PERSON_CITY_TTL, TimeUnit.MINUTES);
            return Result.ok(200, maps);
        } else {
            String key = PERSON_STREET_KEY + street;
            String Json = stringRedisTemplate.opsForValue().get(key);
            if (Json != null) {
                return Result.ok(200, JSONUtil.toList(Json, Map.class));
            }
            QueryWrapper<Personnel> queryWrapper = new QueryWrapper<>();
            queryWrapper
                    .eq("city", city)
                    .eq("street", street)
                    .select("address", "count(*) as num")
                    .groupBy("address");
            List<Map<String, Object>> maps = personnelDao.selectMaps(queryWrapper);
            stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(maps), PERSON_STREET_TTL, TimeUnit.MINUTES);
            return Result.ok(200, maps);
        }
    }

    @Override
    public Result findByUser() {
        UserDTO user = UserHolder.getUser();
        String username = user.getUsername();

        String key = PERSON_USERNAME_KEY + username;

        String Json = stringRedisTemplate.opsForValue().get(key);

        if (Json != null) {
            return Result.ok(200, JSONUtil.toBean(Json, Personnel.class));
        }

        QueryWrapper<Personnel> wrapper = Wrappers.query();
        wrapper.eq("username", username);

        Personnel personnel = getOne(wrapper);

        if (personnel == null) {
            return Result.ok(200, new Personnel());
        }

        stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(personnel), PERSON_USERNAME_TTL, TimeUnit.MINUTES);

        return Result.ok(200, personnel);
    }

    @Override
    public Result saveUser(Personnel personnel) {
        String username = UserHolder.getUser().getUsername();
        personnel.setUsername(username);
        String key = PERSON_USERNAME_KEY + username;
        String str = stringRedisTemplate.opsForValue().get(key);
        System.out.println("saveUser测试" + str);
        if (StrUtil.isBlank(str)) {
            /**
             * 新增居民信息
             */
            boolean isSave = save(personnel);
            if (!isSave) {
                return Result.fail(201, MessageConstant.ADD_PERSON_FAIL);
            }
            return Result.ok(200, personnel);
        } else {
            /**
             * 修改用户信息
             */
            Integer id = JSONUtil.toBean(str, Personnel.class).getId();
            personnel.setId(id);
            boolean isUpdate = updateById(personnel);
            if (!isUpdate) {
                return Result.fail(201, MessageConstant.PERSON_UPDATE_FAIL);
            }

            stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(personnel), PERSON_ID_TTL, TimeUnit.MINUTES);
            return Result.ok(200, personnel);
        }
    }
}
